package com.mrogrape.util;

/**
 * 这个类实现了一个循环的序列.
 * 
 * 与一般的序列不同，当这个序列指针已经移至最大值时，它将再次返回该序列范围
 * 的起始点。
 * <p>该序列具有以下的属性：
 * <ul>
 * <li>最小值 ：默认为0;
 * <li>最大值 ：默认为long型的最大值;
 * <li>起始值 ：序列起始时指针所在的位置 默认为最小值;
 * <li>步进      ：指针每次移动的距离，默认为1;
 * </ul>
 * 这些属性在创建时被指定，并且无法修改。
 * 
 * <p>
 * <b>注意</b> ：指针从序列尾移至序列头时需要消耗一个步进值（而不是一次步进）。
 * <p>
 * @author  Ice Spring
 * @version 1.0.20110827
 */
public class LoopSequence {

	/**
	 * 创建序列，这个序列将以Long型的最大值为最大值。
	 */
	public LoopSequence(){
		this(Long.MAX_VALUE);
	}

	/**
	 * 创建循环序列并指定其最大值。
	 * 
	 * @param maxValue <code>long</code>型 最大值。
	 */
	public LoopSequence(long maxValue){
		this(0,maxValue,0);
	}

	/**
	 * 创建序列并指定其最大值和最小值。
	 * 
	 * @param minValue <code>long</code>型 最小值。
	 * @param maxValue <code>long</code>型 最大值。
	 */
	public LoopSequence(long minValue,long maxValue){
		this(minValue,maxValue,minValue);
	}

	/**
	 * 创建序列并指定其最大值，最小值以及起始值。
	 * 
	 * @param minValue <code>long</code>型 最小值
	 * @param maxValue <code>long</code>型 最大值
	 * @param startValue <code>long</code>型 起始值
	 */
	public LoopSequence(long minValue, long maxValue, long startValue) {
		this(minValue,maxValue,minValue,1);

	}

	/**
	 * 创建序列并指定其最大值，最小值，起始值和步进值。
	 * 
	 * @param minValue <code>long</code>型 最小值
	 * @param maxValue <code>long</code>型 最大值
	 * @param startValue <code>long</code>型 起始值
	 * @param step <code>int</code>型 步进值
	 */
	public LoopSequence(long minValue, long maxValue, long startValue,int step) {
		this.minValue = minValue;
		this.maxValue = maxValue;
		this.startValue = startValue;
		this.step = step;
		this.nowValue = startValue;

		//validate
		if(minValue>maxValue||minValue==maxValue){
			throw new IllegalArgumentException("The min value must be lettle than max value!");
		}
		if(startValue>maxValue || startValue<minValue){
			throw new IllegalArgumentException("The start value must between min value and max value!");
		}
		if(step>(maxValue-minValue)){
			throw new IllegalArgumentException("The step is too big!");
		}
	}

	/**
	 * 获取当前序列值并使序列指针向下移动。
	 * 
	 * @return <code>long</code>型 下一个序列值
	 */
	public synchronized long next(){
		long temp = this.nowValue();
		long nextValue = this.nowValue + this.step;
		if(nextValue>this.maxValue){
			this.nowValue=nextValue-this.maxValue+this.minValue-1;
		}else{
			this.nowValue+=this.step;
		}
		return temp;
	}

	/**
	 * 获取当前的序列值而不执行+1的步骤。
	 * 
	 * @return
	 */
	public long nowValue(){
		return this.nowValue;
	}

	/**
	 * 重置序列为初始状态。
	 */
	public void reset(){
		this.nowValue = this.startValue;
	}

	private long minValue = 0;
	private long maxValue = 1;
	private long startValue = 0;
	private long nowValue = 0;
	private int step = 1;


}
